//
// Created by cktor on 2018/7/1.
//

#include "EPRom.h"
#include "LOG.h"

#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <stdio.h>
#include <stdlib.h>

int smbus_fd = -1;

typedef struct i2c_ioctl_data {
    struct i2c_msg __user *msgs; /* pointers to i2c_msgs */
    __u32 nmsgs; /* number of i2c_msgs */
} I2C_DATA;


/**
 * 初始化 EPROM 部分
 * @param dev_name 文件路径信息
 * @return 0，打开文件成功；反之，其他
 */
int InitI2c_EPROM(char *dev_name) {
    if (smbus_fd != -1) {
        return -1;
    }
    if ((smbus_fd = open(dev_name, O_RDWR | O_NONBLOCK)) < 0) {
        LOGE("open %s failed:%s\n", dev_name, strerror(errno));
        return -1;
    }
    ioctl(smbus_fd, I2C_RETRIES, 6);
    LOGE("open %s sucessed\n", dev_name);
    return 0;
}

/**
 * 关闭 EPROM 部分
 * @return 0，如果关闭成功；反之，其他
 */
int CloseI2c_EPROM(void) {
    if (smbus_fd >= 0) {
        close(smbus_fd);
        smbus_fd = -1;
        return 0;
    }
    return -1;
}

/**
 * 执行写EPROM的操作
 * @param slave 暂时固定部分，当前状态下，始终为 0xa0 >> 1
 * @param regAddr 开始写地址
 * @param buf 数据内容
 * @param len 写长度
 * @return 0，如果成功；反之，其他
 */
int
I2cRead_EPROM(unsigned char slave, unsigned char regAddr, unsigned char *buf, unsigned char len) {

    if (smbus_fd <= 0)
        return -1;

    I2C_DATA d;
    struct i2c_msg m[2];
    unsigned char regBuf[1] = {regAddr};

    m[0].addr = slave;
    m[0].flags = 0;
    m[0].len = 1;
    m[0].buf = (__u8 *) regBuf;

    m[1].addr = slave;
    m[1].flags = I2C_M_RD;
    m[1].len = len;
    m[1].buf = buf;
    d.msgs = m;
    d.nmsgs = 2;
    if (ioctl(smbus_fd, I2C_RDWR, &d) < 0) {
        LOGE("ioctl read failed: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

/**
 * 执行读EPROM的操作
 * @param slave 暂时固定部分，当前状态下，始终为 0xa0 >> 1
 * @param regAddr 开始读地址
 * @param buf 读取到的数据长度
 * @param len 要执行读取的长度
 * @return 0，如果成功；反之，其他
 */
int
I2cWrite_EPROM(unsigned char slave, unsigned char regAddr, unsigned char *buf, unsigned char len) {

    if (smbus_fd <= 0)
        return -1;

    I2C_DATA d;
    int ret = 0;
    char *writeBuf = (char *) malloc(len + 1);
    memset(writeBuf, 0, len + 1);
    writeBuf[0] = regAddr;
    memcpy(&writeBuf[1], buf, len);
    struct i2c_msg m[1];
    m[0].addr = slave;
    m[0].flags = 0;
    m[0].len = len + 1;
    m[0].buf = (__u8 *) writeBuf;
    d.msgs = m;
    d.nmsgs = 1;
    if (ioctl(smbus_fd, I2C_RDWR, &d) < 0) {
        LOGE("ioctl I2C_RDWR failed: %s\n", strerror(errno));
        ret = -1;
    } else {
        LOGE("ioctl I2C_RDWR sucessed\n");
    }

    end:
    free(writeBuf);
    return ret;
}